home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume18 / elm2.2 / part23 < prev    next >
Encoding:
Internet Message Format  |  1989-04-12  |  49.1 KB

  1. Subject:  v18i102:  Elm mail system, release 2.2, Part23/22
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: dsinc!syd@uunet.UU.NET (Syd Weinstein)
  7. Posting-number: Volume 18, Issue 102
  8. Archive-name: elm2.2/part23
  9.  
  10. #!/bin/sh
  11. # this is part 23 of a multipart archive
  12. # do not concatenate these parts, unpack them in order with /bin/sh
  13. # file utils/arepdaem.c continued
  14. #
  15. CurArch=23
  16. if test ! -r s2_seq_.tmp
  17. then echo "Please unpack part 1 first!"
  18.      exit 1; fi
  19. ( read Scheck
  20.   if test "$Scheck" != $CurArch
  21.   then echo "Please unpack part $Scheck next!"
  22.        exit 1;
  23.   else exit 0; fi
  24. ) < s2_seq_.tmp || exit 1
  25. echo "x - Continuing file utils/arepdaem.c"
  26. sed 's/^X//' << 'SHAR_EOF' >> utils/arepdaem.c
  27. X       }
  28. X}
  29. X
  30. Xremove_first_word(string)
  31. Xchar *string;
  32. X{    /** removes first word of string, ie up to first non-white space
  33. X        following a white space! **/
  34. X
  35. X    register int loc;
  36. X
  37. X    for (loc = 0; string[loc] != ' ' && string[loc] != '\0'; loc++) 
  38. X        ;
  39. X
  40. X    while (string[loc] == ' ' || string[loc] == '\t')
  41. X      loc++;
  42. X    
  43. X    move_left(string, loc);
  44. X}
  45. X
  46. Xmove_left(string, chars)
  47. Xchar string[];
  48. Xint  chars;
  49. X{
  50. X    /** moves string chars characters to the left DESTRUCTIVELY **/
  51. X
  52. X    register int i;
  53. X
  54. X    chars--; /* index starting at zero! */
  55. X
  56. X    for (i=chars; string[i] != '\0' && string[i] != '\n'; i++)
  57. X      string[i-chars] = string[i];
  58. X
  59. X    string[i-chars] = '\0';
  60. X}
  61. X
  62. Xreply_to_mail(person, from, subject)
  63. Xint   person;
  64. Xchar *from, *subject;
  65. X{
  66. X    /** Respond to the message from the specified person with the
  67. X        specified subject... **/
  68. X    
  69. X    char buffer[SLEN];
  70. X
  71. X    if (strlen(subject) == 0)
  72. X      strcpy(subject, "Auto-reply Mail");
  73. X    else if (! first_word(subject,"Auto-reply")) {
  74. X      sprintf(buffer, "Auto-reply to:%s", subject);
  75. X      strcpy(subject, buffer);
  76. X    }
  77. X
  78. X    log("auto-replying to '%s'", from);
  79. X
  80. X    mail(from, subject, reply_table[person].replyfile, person);
  81. X}    
  82. X
  83. Xreverse(string)
  84. Xchar *string;
  85. X{
  86. X    /** reverse string... pretty trivial routine, actually! **/
  87. X
  88. X    char buffer[SLEN];
  89. X    register int i, j = 0;
  90. X
  91. X    for (i = strlen(string)-1; i >= 0; i--)
  92. X      buffer[j++] = string[i];
  93. X
  94. X    buffer[j] = '\0';
  95. X
  96. X    strcpy(string, buffer);
  97. X}
  98. X
  99. Xlong
  100. Xbytes(name)
  101. Xchar *name;
  102. X{
  103. X    /** return the number of bytes in the specified file.  This
  104. X        is to check to see if new mail has arrived....  **/
  105. X
  106. X    int ok = 1;
  107. X    extern int errno;    /* system error number! */
  108. X    struct stat buffer;
  109. X
  110. X    if (stat(name, &buffer) != 0)
  111. X      if (errno != 2) {
  112. X       unlock();
  113. X       exit(fprintf(stderr,"Error %d attempting fstat on %s", errno, name));
  114. X      }
  115. X      else
  116. X        ok = 0;
  117. X    
  118. X    return(ok ? buffer.st_size : 0);
  119. X}
  120. X
  121. Xmail(to, subject, filename, person)
  122. Xchar *to, *subject, *filename;
  123. Xint   person;
  124. X{
  125. X    /** Mail 'file' to the user from person... **/
  126. X    
  127. X    char buffer[VERY_LONG_STRING];
  128. X
  129. X    sprintf(buffer, "%s -f '%s [autoreply]' -s '%s' %s %s",
  130. X        fastmail, reply_table[person].username,
  131. X            subject, filename, to);
  132. X    
  133. X    system(buffer);
  134. X}
  135. X
  136. Xlog(message, arg)
  137. Xchar *message;
  138. Xchar *arg;
  139. X{
  140. X    /** Put log entry into log file.  Use the format:
  141. X          date-time: <message>
  142. X    **/
  143. X
  144. X    struct tm *localtime(), *thetime;
  145. X    long      time(), clock;
  146. X    char      buffer[SLEN];
  147. X
  148. X    /** first off, get the time and date **/
  149. X
  150. X    clock = time((long *) 0);       /* seconds since ???   */
  151. X    thetime = localtime(&clock);    /* and NOW the time... */
  152. X
  153. X    /** then put the message out! **/
  154. X
  155. X    sprintf(buffer, message, arg);
  156. X
  157. X    fprintf(logfd,"%d/%d-%d:%02d: %s\n", 
  158. X        thetime->tm_mon+1, thetime->tm_mday,
  159. X            thetime->tm_hour,  thetime->tm_min,
  160. X            buffer);
  161. X}
  162. X
  163. XFILE *open_logfile()
  164. X{
  165. X    /** open the logfile.  returns a valid file descriptor **/
  166. X
  167. X    FILE *fd;
  168. X
  169. X    if ((fd = fopen(logfile, "a")) == NULL)
  170. X      if ((fd = fopen(logfile2, "a")) == NULL) {
  171. X        unlock();
  172. X        exit(1);    /* give up! */
  173. X      }
  174. X
  175. X    return( (FILE *) fd);
  176. X}
  177. X
  178. Xclose_logfile()
  179. X{
  180. X    /** Close the logfile until needed again. **/
  181. X
  182. X    fclose(logfd);
  183. X}
  184. X
  185. Xchar *strip_parens(string)
  186. Xchar *string;
  187. X{
  188. X    /** Return string with all parenthesized information removed.
  189. X        This is a non-destructive algorithm... **/
  190. X
  191. X    static char  buffer[SLEN];
  192. X    register int i, depth = 0, buffer_index = 0;
  193. X
  194. X    for (i=0; i < strlen(string); i++) {
  195. X      if (string[i] == '(')
  196. X        depth++;
  197. X      else if (string[i] == ')') 
  198. X        depth--;
  199. X      else if (depth == 0)
  200. X        buffer[buffer_index++] = string[i];
  201. X    }
  202. X    
  203. X    buffer[buffer_index] = '\0';
  204. X
  205. X    return( (char *) buffer);
  206. X}
  207. X
  208. X/*** LOCK and UNLOCK - ensure only one copy of this daemon running at any
  209. X     given time by using a file existance semaphore (wonderful stuff!) ***/
  210. X
  211. Xlock()
  212. X{
  213. X    /** Try to create the lock file.  If it's there, or we can't
  214. X        create it for some stupid reason, return zero, otherwise,
  215. X        a non-zero return code indicates success in locking this
  216. X        process in. **/
  217. X
  218. X    if (access(arep_lock_file, EXISTS) == 0)
  219. X      return(0);     /* file already exists!! */
  220. X
  221. X    if (creat(arep_lock_file, MODE) == -1)
  222. X      return(0);    /* can't create file!!   */
  223. X
  224. X    return(1);
  225. X}
  226. X
  227. Xunlock()
  228. X{
  229. X    /** remove lock file if it's there! **/
  230. X
  231. X    (void) unlink(arep_lock_file);
  232. X}
  233. SHAR_EOF
  234. echo "File utils/arepdaem.c is complete"
  235. chmod 0444 utils/arepdaem.c || echo "restore of utils/arepdaem.c fails"
  236. echo "x - extracting utils/autoreply.c (Text)"
  237. sed 's/^X//' << 'SHAR_EOF' > utils/autoreply.c &&
  238. X
  239. Xstatic char rcsid[] = "@(#)$Id: autoreply.c,v 2.3 89/03/25 21:47:41 syd Exp $";
  240. X
  241. X/*******************************************************************************
  242. X *  The Elm Mail System  -  $Revision: 2.3 $   $State: Exp $
  243. X *
  244. X *             Copyright (c) 1986, 1987 Dave Taylor
  245. X *             Copyright (c) 1988, 1989 USENET Community Trust
  246. X *******************************************************************************
  247. X * Bug reports, patches, comments, suggestions should be sent to:
  248. X *
  249. X *    Syd Weinstein, Elm Coordinator
  250. X *    elm@dsinc.UUCP            dsinc!elm
  251. X *
  252. X *******************************************************************************
  253. X * $Log:    autoreply.c,v $
  254. X * Revision 2.3  89/03/25  21:47:41  syd
  255. X * Initial 2.2 Release checkin
  256. X * 
  257. X *
  258. X ******************************************************************************/
  259. X
  260. X/** This is the front-end for the autoreply system, and performs two 
  261. X    functions: it either adds the user to the list of people using the
  262. X    autoreply function (starting the daemon if no-one else) or removes
  263. X    a user from the list of people.
  264. X
  265. X    Usage:  autoreply filename
  266. X        autoreply "off"
  267. X    or  autoreply        [to find current status]
  268. X    
  269. X**/
  270. X
  271. X#include <stdio.h>
  272. X#include <errno.h>
  273. X#include <sys/types.h>
  274. X#include <sys/stat.h>
  275. X
  276. X#include "defs.h"
  277. X
  278. Xstatic char ident[] = { WHAT_STRING };
  279. X
  280. X#define  tempdir    "/tmp/arep"        /* file prefix          */
  281. X#define  autoreply_file    "/etc/autoreply.data"   /* autoreply data file  */
  282. X
  283. Xextern   int errno;                /* system error code    */
  284. Xchar     username[NLEN];            /* login name of user   */
  285. X
  286. Xmain(argc, argv)
  287. Xint    argc;
  288. Xchar *argv[];
  289. X{
  290. X    char filename[SLEN];
  291. X
  292. X    if (argc > 2) {
  293. X      printf("Usage: %s <filename>\tto start autoreply,\n", argv[0]);
  294. X      printf("       %s off\t\tto turn off autoreply\n", argv[0]);
  295. X      printf("   or  %s    \t\tto check current status\n", argv[0]);
  296. X      exit(1);
  297. X    }
  298. X
  299. X    (void) cuserid(username);
  300. X
  301. X    if (argc == 1 || strcmp(argv[1], "off") == 0) 
  302. X      remove_user((argc == 1));
  303. X    else {
  304. X      strcpy(filename, argv[1]);
  305. X      if (access(filename,READ_ACCESS) != 0) {
  306. X        printf("Error: Can't read file '%s'\n", filename);
  307. X        exit(1);
  308. X      }
  309. X      
  310. X      if (filename[0] != '/') /* prefix home directory */
  311. X        sprintf(filename,"%s/%s", getenv("HOME"), argv[1]);
  312. X
  313. X      add_user(filename);
  314. X    }
  315. X
  316. X    exit(0);
  317. X}
  318. X
  319. Xremove_user(stat_only)
  320. Xint stat_only;
  321. X{
  322. X    /** Remove the user from the list of currently active autoreply 
  323. X        people.  If 'stat_only' is set, then just list the name of
  324. X        the file being used to autoreply with, if any. **/
  325. X
  326. X    FILE *temp, *repfile;
  327. X    char  tempfile[SLEN], user[SLEN], filename[SLEN];
  328. X    int   c, copied = 0, found = 0;
  329. X    long  filesize, bytes();
  330. X
  331. X    if (! stat_only) {
  332. X      sprintf(tempfile, "%s.%06d", tempdir, getpid());
  333. X
  334. X      if ((temp = fopen(tempfile, "w")) == NULL) {
  335. X        printf("Error: couldn't open tempfile '%s'.  Not removed\n",
  336. X            tempfile);
  337. X        exit(1);
  338. X      }
  339. X    }
  340. X
  341. X    if ((repfile = fopen(autoreply_file, "r")) == NULL) {
  342. X      if (stat_only) {
  343. X        printf("You're not currently autoreplying to mail.\n");
  344. X        exit(0);
  345. X      }
  346. X      printf("No-one is autoreplying to their mail!\n");
  347. X      exit(0);
  348. X    }
  349. X
  350. X    /** copy out of real replyfile... **/
  351. X
  352. X    while (fscanf(repfile, "%s %s %ld", user, filename, &filesize) != EOF) 
  353. X
  354. X      if (strcmp(user, username) != 0) {
  355. X        if (! stat_only) {
  356. X          copied++;
  357. X          fprintf(temp, "%s %s %ld\n", user, filename, filesize);
  358. X        }
  359. X      }
  360. X      else {
  361. X        if (stat_only) {
  362. X          printf("You're currently autoreplying to mail with the file %s\n",              filename); 
  363. X          exit(0);
  364. X        }
  365. X        found++;
  366. X      }
  367. X
  368. X    fclose(temp);
  369. X    fclose(repfile);
  370. X
  371. X    if (! found) {
  372. X      printf("You're not currently autoreplying to mail%s\n",
  373. X          stat_only? "." : "!");
  374. X      if (! stat_only)
  375. X        unlink(tempfile);
  376. X      exit(! stat_only);
  377. X    }
  378. X
  379. X    /** now copy tempfile back into replyfile **/
  380. X
  381. X    if (copied == 0) {    /* removed the only person! */
  382. X      unlink(autoreply_file);
  383. X    }
  384. X    else {            /* save everyone else   */
  385. X      
  386. X      if ((temp = fopen(tempfile,"r")) == NULL) {
  387. X        printf("Error: couldn't reopen tempfile '%s'.  Not removed.\n",
  388. X            tempfile);
  389. X        unlink(tempfile);
  390. X        exit(1);
  391. X      }
  392. X
  393. X      if ((repfile = fopen(autoreply_file, "w")) == NULL) {
  394. X        printf(
  395. X          "Error: couldn't reopen autoreply file for writing!  Not removed.\n");
  396. X        unlink(tempfile);
  397. X        exit(1);
  398. X      }
  399. X
  400. X      while ((c = getc(temp)) != EOF)
  401. X        putc(c, repfile);
  402. X
  403. X      fclose(temp);
  404. X      fclose(repfile);
  405. X    
  406. X    }
  407. X    unlink(tempfile);
  408. X
  409. X    if (found > 1)
  410. X      printf("Warning: your username appeared %d times!!   Removed all\n", 
  411. X          found);
  412. X    else
  413. X      printf("You've been removed from the autoreply table.\n");
  414. X}
  415. X
  416. Xadd_user(filename)
  417. Xchar *filename;
  418. X{
  419. X    /** add the user to the autoreply file... **/
  420. X
  421. X    FILE *repfile;
  422. X    char  mailfile[SLEN];
  423. X    long  bytes();
  424. X
  425. X    if ((repfile = fopen(autoreply_file, "a")) == NULL) {
  426. X      printf("Error: couldn't open the autoreply file!  Not added\n");
  427. X      exit(1);
  428. X    }
  429. X    
  430. X    sprintf(mailfile,"%s/%s", mailhome, username);
  431. X
  432. X    fprintf(repfile,"%s %s %ld\n", username, filename, bytes(mailfile));
  433. X
  434. X    fclose(repfile);
  435. X
  436. X    printf("You've been added to the autoreply system.\n");
  437. X}
  438. X
  439. X
  440. Xlong
  441. Xbytes(name)
  442. Xchar *name;
  443. X{
  444. X    /** return the number of bytes in the specified file.  This
  445. X        is to check to see if new mail has arrived....  **/
  446. X
  447. X    int ok = 1;
  448. X    extern int errno;    /* system error number! */
  449. X    struct stat buffer;
  450. X
  451. X    if (stat(name, &buffer) != 0)
  452. X      if (errno != 2)
  453. X       exit(fprintf(stderr,"Error %d attempting fstat on %s", errno, name));
  454. X      else
  455. X        ok = 0;
  456. X    
  457. X    return(ok ? buffer.st_size : 0L);
  458. X}
  459. SHAR_EOF
  460. chmod 0444 utils/autoreply.c || echo "restore of utils/autoreply.c fails"
  461. echo "x - extracting utils/checkalias (Text)"
  462. sed 's/^X//' << 'SHAR_EOF' > utils/checkalias &&
  463. X: Use /bin/sh
  464. X# checkalias: part of the Elm mail system
  465. X# @(#)$Id: checkalias,v 2.1 89/03/03 17:46:56 syd Exp $
  466. Xif [ "$*" = "" ]; then
  467. X  echo Usage: checkalias alias \[alias ...\] 1>&2
  468. X  exit 1
  469. Xfi
  470. Xexec elm -c $*
  471. SHAR_EOF
  472. chmod 0444 utils/checkalias || echo "restore of utils/checkalias fails"
  473. echo "x - extracting utils/expand.c (Text)"
  474. sed 's/^X//' << 'SHAR_EOF' > utils/expand.c &&
  475. X
  476. Xstatic char rcsid[] = "@(#)$Id: expand.c,v 2.3 89/03/25 21:47:43 syd Exp $";
  477. X
  478. X/*******************************************************************************
  479. X *  The Elm Mail System  -  $Revision: 2.3 $   $State: Exp $
  480. X *
  481. X *             Copyright (c) 1986, 1987 Dave Taylor
  482. X *             Copyright (c) 1988, 1989 USENET Community Trust
  483. X *******************************************************************************
  484. X * Bug reports, patches, comments, suggestions should be sent to:
  485. X *
  486. X *    Syd Weinstein, Elm Coordinator
  487. X *    elm@dsinc.UUCP            dsinc!elm
  488. X *
  489. X *******************************************************************************
  490. X * $Log:    expand.c,v $
  491. X * Revision 2.3  89/03/25  21:47:43  syd
  492. X * Initial 2.2 Release checkin
  493. X * 
  494. X *
  495. X ******************************************************************************/
  496. X
  497. X/** This is a library routine for the various utilities that allows
  498. X    users to have the standard 'Elm' folder directory nomenclature
  499. X    for all filenames (e.g. '+', '=' or '%').  It should be compiled
  500. X    and then linked in as needed.
  501. X
  502. X**/
  503. X
  504. X#include <stdio.h>
  505. X#include "defs.h"
  506. X
  507. Xchar *expand_define();
  508. X
  509. Xint
  510. Xexpand(filename)
  511. Xchar *filename;
  512. X{
  513. X    /** Expand the filename since the first character is a meta-
  514. X        character that should expand to the "maildir" variable
  515. X        in the users ".elmrc" file...
  516. X
  517. X        Note: this is a brute force way of getting the entry out 
  518. X        of the .elmrc file, and isn't recommended for the faint 
  519. X        of heart!
  520. X    **/
  521. X
  522. X    FILE *rcfile;
  523. X    char  buffer[SLEN], *expanded_dir, *home, *getenv(), *bufptr;
  524. X    int   foundit = 0;
  525. X
  526. X    bufptr = (char *) buffer;        /* same address */
  527. X    
  528. X    if ((home = getenv("HOME")) == NULL) {
  529. X      printf(
  530. X         "Can't expand environment variable $HOME to find .elmrc file!\n");
  531. X      exit(1);
  532. X    }
  533. X
  534. X    sprintf(buffer, "%s/%s", home, elmrcfile);
  535. X
  536. X    if ((rcfile = fopen(buffer, "r")) == NULL) {
  537. X      printf("Can't open your \".elmrc\" file (%s) for reading!\n",
  538. X         buffer);
  539. X      exit(1);
  540. X    }
  541. X
  542. X    while (fgets(buffer, SLEN, rcfile) != NULL && ! foundit) {
  543. X      if (strncmp(buffer, "maildir", 7) == 0 ||
  544. X          strncmp(buffer, "folders", 7) == 0) {
  545. X        while (*bufptr != '=' && *bufptr) 
  546. X          bufptr++;
  547. X        bufptr++;            /* skip the equals sign */
  548. X        while (whitespace(*bufptr) && *bufptr)
  549. X          bufptr++; 
  550. X        home = bufptr;        /* remember this address */
  551. X
  552. X        while (! whitespace(*bufptr) && *bufptr != '\n')
  553. X          bufptr++;
  554. X
  555. X        *bufptr = '\0';        /* remove trailing space */
  556. X        foundit++;
  557. X      }
  558. X    }
  559. X
  560. X    fclose(rcfile);            /* be nice... */
  561. X
  562. X    if (! foundit) {
  563. X      printf("Couldn't find \"maildir\" in your .elmrc file!\n");
  564. X      exit(1);
  565. X    }
  566. X
  567. X    /** Home now points to the string containing your maildir, with
  568. X        no leading or trailing white space...
  569. X    **/
  570. X
  571. X    expanded_dir = expand_define(home);
  572. X
  573. X    sprintf(buffer, "%s%s%s", expanded_dir, 
  574. X        (expanded_dir[strlen(expanded_dir)-1] == '/' ||
  575. X        filename[0] == '/') ? "" : "/", (char *) filename+1);
  576. X
  577. X    strcpy(filename, buffer);
  578. X}
  579. X
  580. Xchar *expand_define(maildir)
  581. Xchar *maildir;
  582. X{
  583. X    /** This routine expands any occurances of "~" or "$var" in
  584. X        the users definition of their maildir directory out of
  585. X        their .elmrc file.
  586. X
  587. X        Again, another routine not for the weak of heart or staunch
  588. X        of will!
  589. X    **/
  590. X
  591. X    static char buffer[SLEN];    /* static buffer AIEE!! */
  592. X    char   name[SLEN],        /* dynamic buffer!! (?) */
  593. X           *nameptr,           /*  pointer to name??     */
  594. X           *value;              /* char pointer for munging */
  595. X
  596. X    if (*maildir == '~') 
  597. X      sprintf(buffer, "%s%s", getenv("HOME"), ++maildir);
  598. X    else if (*maildir == '$') {     /* shell variable */
  599. X
  600. X      /** break it into a single word - the variable name **/
  601. X
  602. X      strcpy(name, (char *) maildir + 1);    /* hurl the '$' */
  603. X      nameptr = (char *) name;
  604. X      while (*nameptr != '/' && *nameptr) nameptr++;
  605. X      *nameptr = '\0';    /* null terminate */
  606. X      
  607. X      /** got word "name" for expansion **/
  608. X
  609. X      if ((value = getenv(name)) == NULL) {
  610. X        printf("Couldn't expand shell variable $%s in .elmrc!\n", name);
  611. X        exit(1);
  612. X      }
  613. X      sprintf(buffer, "%s%s", value, maildir + strlen(name) + 1);
  614. X    }
  615. X    else strcpy(buffer, maildir);
  616. X
  617. X    return( ( char *) buffer);
  618. X}
  619. SHAR_EOF
  620. chmod 0444 utils/expand.c || echo "restore of utils/expand.c fails"
  621. echo "x - extracting utils/fastmail.c (Text)"
  622. sed 's/^X//' << 'SHAR_EOF' > utils/fastmail.c &&
  623. X
  624. Xstatic char rcsid[] = "@(#)$Id: fastmail.c,v 2.5 89/03/25 21:47:44 syd Exp $";
  625. X
  626. X/*******************************************************************************
  627. X *  The Elm Mail System  -  $Revision: 2.5 $   $State: Exp $
  628. X *
  629. X *             Copyright (c) 1986, 1987 Dave Taylor
  630. X *             Copyright (c) 1988, 1989 USENET Community Trust
  631. X *******************************************************************************
  632. X * Bug reports, patches, comments, suggestions should be sent to:
  633. X *
  634. X *    Syd Weinstein, Elm Coordinator
  635. X *    elm@dsinc.UUCP            dsinc!elm
  636. X *
  637. X *******************************************************************************
  638. X * $Log:    fastmail.c,v $
  639. X * Revision 2.5  89/03/25  21:47:44  syd
  640. X * Initial 2.2 Release checkin
  641. X * 
  642. X *
  643. X ******************************************************************************/
  644. X
  645. X/** This program is specifically written for group mailing lists and
  646. X    such batch type mail processing.  It does NOT use aliases at all,
  647. X    it does NOT read the /etc/password file to find the From: name
  648. X    of the user and does NOT expand any addresses.  It is meant 
  649. X    purely as a front-end for either /bin/mail or /usr/lib/sendmail
  650. X    (according to what is available on the current system).
  651. X
  652. X         **** This program should be used with CAUTION *****
  653. X
  654. X**/
  655. X
  656. X/** The calling sequence for this program is:
  657. X
  658. X    fastmail {args}  filename full-email-address 
  659. X
  660. X   where args could be any (or all) of;
  661. X
  662. X       -b bcc-list        (Blind carbon copies to)
  663. X       -c cc-list        (carbon copies to)
  664. X       -d            (debug on)
  665. X       -f from         (from name)
  666. X       -F from-addr        (the actual address to be put in the From: line)
  667. X       -r reply-to-address     (Reply-To:)
  668. X       -s subject         (subject of message)
  669. X**/
  670. X
  671. X#include <stdio.h>
  672. X#include "defs.h"
  673. X#include "patchlevel.h"
  674. X
  675. X#ifdef BSD
  676. X# ifdef TMINSYS
  677. X#   include <sys/time.h>
  678. X# else
  679. X#   include <time.h>
  680. X#   include <sys/types.h>
  681. X#   include <sys/timeb.h>
  682. X# endif
  683. X#else
  684. X#  include <time.h>
  685. X#endif
  686. X
  687. Xstatic char ident[] = { WHAT_STRING };
  688. X
  689. X#define  binrmail    "/bin/rmail"
  690. X#define  temphome    "/tmp/fastmail."
  691. X
  692. X
  693. Xchar *arpa_dayname[] = { "Sun", "Mon", "Tue", "Wed", "Thu",
  694. X          "Fri", "Sat", "" };
  695. X
  696. Xchar *arpa_monname[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  697. X          "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", ""};
  698. X
  699. Xchar *get_arpa_date();
  700. X
  701. X#ifdef BSD
  702. X  char *timezone();
  703. X#else
  704. X  extern char *tzname[];
  705. X#endif
  706. X
  707. Xmain(argc, argv)
  708. Xint argc;
  709. Xchar *argv[];
  710. X{
  711. X
  712. X    extern char *optarg;
  713. X    extern int optind;
  714. X    FILE *tempfile;
  715. X    char hostname[NLEN], username[NLEN], from_string[SLEN], subject[SLEN];
  716. X    char filename[SLEN], tempfilename[SLEN], command_buffer[256];
  717. X    char replyto[SLEN], cc_list[SLEN], bcc_list[SLEN], to_list[SLEN];
  718. X    char from_addr[SLEN];
  719. X    int  c, sendmail_available, debug = 0;
  720. X
  721. X    subject[0] = '\0';
  722. X    replyto[0] = '\0';
  723. X    cc_list[0] = '\0';
  724. X    bcc_list[0] = '\0';
  725. X    from_addr[0] = '\0';
  726. X
  727. X    while ((c = getopt(argc, argv, "b:c:df:F:r:s:")) != EOF) {
  728. X      switch (c) {
  729. X        case 'b' : strcpy(bcc_list, optarg);        break;
  730. X        case 'c' : strcpy(cc_list, optarg);        break;
  731. X        case 'd' : debug++;                    break;    
  732. X        case 'f' : strcpy(from_string, optarg);    break;
  733. X        case 'F' : strcpy(from_addr, optarg);        break;
  734. X        case 'r' : strcpy(replyto, optarg);        break;
  735. X        case 's' : strcpy(subject, optarg);        break;
  736. X        case '?' :
  737. X          fprintf(stderr,"Usage: fastmail {args} filename address(es)\n");
  738. X          fprintf(stderr, "   where {args} can be;\n");
  739. X          fprintf(stderr,"\t-b bcc-list\n\t-c cc-list\n\t-d\n");
  740. X          fprintf(stderr,"\t-f from-name\n\t-F from-addr\n");
  741. X          fprintf(stderr, "\t-r reply-to\n\t-s subject\n\n");
  742. X          exit(1);
  743. X       }
  744. X    }    
  745. X
  746. X    if (optind > argc) {
  747. X      fprintf(stderr,"Usage: fastmail {args} filename address(es)\n");
  748. X      fprintf(stderr, "   where {args} can be;\n");
  749. X      fprintf(stderr,"\t-b bcc-list\n\t-c cc-list\n\t-d\n\t-f from-name\n");
  750. X      fprintf(stderr,"\t-F from-addr\n");
  751. X      fprintf(stderr, "\t-r reply-to\n\t-s subject\n\n");
  752. X      exit(1);
  753. X    }
  754. X
  755. X    strcpy(filename, argv[optind++]);
  756. X
  757. X    if (optind > argc) {
  758. X      fprintf(stderr,"Usage: fastmail {args} filename address(es)\n");
  759. X      fprintf(stderr, "   where {args} can be;\n");
  760. X      fprintf(stderr,"\t-b bcc-list\n\t-c cc-list\n\t-d\n\t-f from-name\n");
  761. X      fprintf(stderr,"\t-F from-addr\n");
  762. X      fprintf(stderr,"\t-r reply-to\n\t-s subject\n\n");
  763. X      exit(1);
  764. X    }
  765. X
  766. X#ifdef HOSTCOMPILED
  767. X    strncpy(hostname, HOSTNAME, sizeof(hostname));
  768. X#else
  769. X    gethostname(hostname, sizeof(hostname));
  770. X#endif
  771. X
  772. X    strcpy(username, getlogin());
  773. X
  774. X    if (strlen(username) == 0)
  775. X      cuserid(username);
  776. X
  777. X    if (access(filename, READ_ACCESS) == -1)
  778. X      exit(fprintf(stderr, "Error: can't find file %s!\n", filename));
  779. X
  780. X    sprintf(tempfilename, "%s%d", temphome, getpid());
  781. X
  782. X    if ((tempfile = fopen(tempfilename, "w")) == NULL)
  783. X      exit(fprintf(stderr, "Couldn't open temp file %s\n", tempfilename));
  784. X
  785. X    /** Subject must appear even if "null" and must be first
  786. X        at top of headers for mail because the
  787. X        pure System V.3 mailer, in its infinite wisdom, now
  788. X        assumes that anything the user sends is part of the 
  789. X        message body unless either:
  790. X        1. the "-s" flag is used (although it doesn't seem
  791. X           to be supported on all implementations??)
  792. X        2. the first line is "Subject:".  If so, then it'll
  793. X           read until a blank line and assume all are meant
  794. X           to be headers.
  795. X        So the gory solution here is to move the Subject: line
  796. X        up to the top.  I assume it won't break anyone elses program
  797. X        or anything anyway (besides, RFC-822 specifies that the *order*
  798. X        of headers is irrelevant).  Gahhhhh....
  799. X    **/
  800. X    fprintf(tempfile, "Subject: %s\n", subject);
  801. X
  802. X    if (strlen(from_string) > 0)
  803. X      if (strlen(from_addr) > 0)
  804. X          fprintf(tempfile, "From: %s (%s)\n", from_addr, from_string);
  805. X      else
  806. X          fprintf(tempfile, "From: %s!%s (%s)\n", hostname, username, 
  807. X              from_string);
  808. X    else
  809. X      if (strlen(from_addr) > 0)
  810. X        fprintf(tempfile, "From: %s\n", from_addr);
  811. X      else
  812. X        fprintf(tempfile, "From: %s!%s\n", hostname, username);
  813. X
  814. X    fprintf(tempfile, "Date: %s\n", get_arpa_date());
  815. X
  816. X    if (strlen(replyto) > 0)
  817. X      fprintf(tempfile, "Reply-To: %s\n", replyto);
  818. X
  819. X    while (optind < argc) 
  820. X          sprintf(to_list, "%s%s%s", to_list, (strlen(to_list) > 0? " ":""), 
  821. X          argv[optind++]);
  822. X    
  823. X    fprintf(tempfile, "To: %s\n", to_list);
  824. X
  825. X    if (strlen(cc_list) > 0)
  826. X      fprintf(tempfile, "Cc: %s\n", cc_list);
  827. X
  828. X    fprintf(tempfile, "X-Mailer: fastmail [version %s PL%d]\n",
  829. X      VERSION, PATCHLEVEL);
  830. X    fprintf(tempfile, "\n");
  831. X
  832. X    fclose(tempfile);
  833. X
  834. X    /** now we'll cat both files to /bin/rmail or sendmail... **/
  835. X
  836. X    sendmail_available = (access(sendmail, EXECUTE_ACCESS) != -1);
  837. X
  838. X    printf("Mailing to %s%s%s%s%s [via %s]\n", to_list,
  839. X        (strlen(cc_list) > 0 ? " ":""), cc_list,
  840. X        (strlen(bcc_list) > 0 ? " ":""), bcc_list,
  841. X        sendmail_available? "sendmail" : "rmail");
  842. X
  843. X    sprintf(command_buffer, "cat %s %s | %s %s %s %s", 
  844. X        tempfilename, filename, 
  845. X            sendmail_available? sendmail : mailer,
  846. X        to_list, cc_list, bcc_list);
  847. X
  848. X    if (debug)
  849. X      printf("%s\n", command_buffer);
  850. X
  851. X    system(command_buffer);
  852. X
  853. X    unlink(tempfilename);
  854. X}
  855. X
  856. X
  857. Xchar *get_arpa_date()
  858. X{
  859. X    /** returns an ARPA standard date.  The format for the date
  860. X        according to DARPA document RFC-822 is exemplified by;
  861. X
  862. X                     Mon, 12 Aug 85 6:29:08 MST
  863. X
  864. X    **/
  865. X
  866. X    static char buffer[SLEN];    /* static character buffer       */
  867. X    struct tm *the_time,        /* Time structure, see CTIME(3C) */
  868. X          *localtime();
  869. X    long       junk;        /* time in seconds....         */
  870. X#ifdef BSD
  871. X#  ifndef TMINSYS
  872. X    struct timeb loc_time;    /* of course this is different! */
  873. X#  else
  874. X    struct  timeval  time_val;        
  875. X    struct  timezone time_zone;
  876. X#  endif
  877. X#endif
  878. X
  879. X#ifdef BSD
  880. X#  ifndef TMINSYS
  881. X    junk = (long) time((long *) 0);
  882. X    ftime(&loc_time);
  883. X#  else
  884. X    gettimeofday(&time_val, &time_zone);
  885. X    junk = time_val.tv_sec;
  886. X#  endif
  887. X#else
  888. X    junk = time(0);    /* this must be here for it to work! */
  889. X#endif
  890. X    the_time = localtime(&junk);
  891. X
  892. X    sprintf(buffer, "%s, %d %s %d %d:%02d:%02d %s",
  893. X      arpa_dayname[the_time->tm_wday],
  894. X      the_time->tm_mday % 32,
  895. X      arpa_monname[the_time->tm_mon],
  896. X      the_time->tm_year % 100,
  897. X      the_time->tm_hour % 24,
  898. X      the_time->tm_min  % 61,
  899. X      the_time->tm_sec  % 61,
  900. X#ifdef BSD
  901. X#  ifndef TMINSYS
  902. X      timezone(loc_time.time_zone, the_time->tz_isdst));
  903. X#  else
  904. X      timezone(time_zone.tz_minuteswest, time_zone.tz_dsttime));
  905. X#  endif
  906. X#else
  907. X      tzname[the_time->tm_isdst]);
  908. X#endif
  909. X    
  910. X    return( (char *) buffer);
  911. X}
  912. SHAR_EOF
  913. chmod 0444 utils/fastmail.c || echo "restore of utils/fastmail.c fails"
  914. echo "x - extracting utils/from.c (Text)"
  915. sed 's/^X//' << 'SHAR_EOF' > utils/from.c &&
  916. X
  917. Xstatic char rcsid[] = "@(#)$Id: from.c,v 2.9 89/03/25 21:47:46 syd Exp $";
  918. X
  919. X/*******************************************************************************
  920. X *  The Elm Mail System  -  $Revision: 2.9 $   $State: Exp $
  921. X *
  922. X *             Copyright (c) 1986, 1987 Dave Taylor
  923. X *             Copyright (c) 1988, 1989 USENET Community Trust
  924. X *******************************************************************************
  925. X * Bug reports, patches, comments, suggestions should be sent to:
  926. X *
  927. X *    Syd Weinstein, Elm Coordinator
  928. X *    elm@dsinc.UUCP            dsinc!elm
  929. X *
  930. X *******************************************************************************
  931. X * $Log:    from.c,v $
  932. X * Revision 2.9  89/03/25  21:47:46  syd
  933. X * Initial 2.2 Release checkin
  934. X * 
  935. X *
  936. X ******************************************************************************/
  937. X
  938. X/** print out whom each message is from in the pending folder or specified 
  939. X    one, including a subject line if available.. 
  940. X
  941. X**/
  942. X
  943. X#include <stdio.h>
  944. X#include <pwd.h>
  945. X#include "defs.h"
  946. X
  947. Xstatic char ident[] = { WHAT_STRING };
  948. X
  949. X#define LINEFEED    (char) 10
  950. X
  951. X#define metachar(c)    (c == '=' || c == '+' || c == '%')
  952. X
  953. XFILE *mailfile;
  954. X
  955. Xchar *expand_define();
  956. Xint   number = 0,    /* should we number the messages?? */
  957. X      verbose = 0;    /* and should we prepend a header? */
  958. X
  959. Xmain(argc, argv)
  960. Xint argc;
  961. Xchar *argv[];
  962. X{
  963. X    char infile[SLEN], *cp ;
  964. X    int  multiple_files = 0, output_files = 0, c;
  965. X    struct passwd *pass, *getpwuid();
  966. X
  967. X    extern int optind;
  968. X
  969. X    while ((c = getopt(argc, argv, "nv")) != EOF) 
  970. X      switch (c) {
  971. X        case (int)'n': number++;        break;
  972. X        case (int)'v': verbose++;    break;
  973. X        case (int)'?': printf("Usage: %s [-n] [-v] {filename | username}\n",
  974. X                 argv[0]);
  975. X                       exit(1);
  976. X      }
  977. X
  978. X    infile[0] = '\0';
  979. X    if (optind == argc) {
  980. X    /*
  981. X     *    determine mail file from environment variable if found,
  982. X     *    else use password entry
  983. X     */
  984. X      if ((cp = getenv("MAIL")) == NULL) {
  985. X        if((pass = getpwuid(getuid())) == NULL) {
  986. X          printf("You have no password entry!");
  987. X          exit(1);
  988. X        }
  989. X        sprintf(infile,"%s%s",mailhome, pass->pw_name);
  990. X      }
  991. X      else
  992. X        strcpy(infile, cp);
  993. X      optind -= 1;    /* ensure one pass through loop */
  994. X    }
  995. X
  996. X    multiple_files = (argc - optind > 1);
  997. X
  998. X    while (optind < argc) {
  999. X    
  1000. X      if (multiple_files) {
  1001. X        strcpy(infile, argv[optind]);
  1002. X        printf("%s%s: \n", output_files++ > 0 ? "\n":"", infile);
  1003. X      }
  1004. X      else if (infile[0] == '\0')
  1005. X        strcpy(infile, argv[optind]);
  1006. X
  1007. X      if (metachar(infile[0])) {
  1008. X        if (expand(infile) == 0) {
  1009. X           fprintf(stderr, "%s: couldn't expand filename %s!\n", 
  1010. X               argv[0], infile);
  1011. X           exit(1);
  1012. X        }
  1013. X      }
  1014. X
  1015. X      if ((mailfile = fopen(infile,"r")) == NULL) {
  1016. X        if (optind+1 == argc)
  1017. X          printf("No mail.\n");
  1018. X        else {
  1019. X          if (infile[0] == '/') 
  1020. X            printf("Couldn't open folder \"%s\".\n", infile);
  1021. X          else {
  1022. X            sprintf(infile,"%s%s", mailhome, argv[optind]);
  1023. X            if ((mailfile = fopen(infile,"r")) == NULL)
  1024. X              printf("Couldn't open folders \"%s\" or \"%s\".\n",
  1025. X             argv[optind], infile);
  1026. X            else if (read_headers()==0)
  1027. X              printf("No messages in that folder!\n");
  1028. X           }
  1029. X        }
  1030. X      }
  1031. X      else
  1032. X        if (read_headers(optind+1 == argc)==0)
  1033. X          if (optind+1 == argc)
  1034. X            printf("No mail\n");
  1035. X          else
  1036. X            printf("No messages in that folder!\n");
  1037. X
  1038. X      optind++;
  1039. X    }
  1040. X    exit(0);
  1041. X}
  1042. X
  1043. Xint
  1044. Xread_headers(user_mailbox)
  1045. Xint user_mailbox;
  1046. X{
  1047. X    /** Read the headers, output as found.  User-Mailbox is to guarantee
  1048. X        that we get a reasonably sensible message from the '-v' option
  1049. X     **/
  1050. X
  1051. X    char buffer[SLEN], from_whom[SLEN], subject[SLEN];
  1052. X    register int subj = 0, in_header = 0, count = 0;
  1053. X
  1054. X    while (fgets(buffer, SLEN, mailfile) != NULL) {
  1055. X      if (first_word(buffer,"From ")) {
  1056. X        if (real_from(buffer, from_whom)) {
  1057. X          subj = 0;
  1058. X          in_header = 1;
  1059. X        }
  1060. X      }
  1061. X      else if (in_header) {
  1062. X        if (first_word(buffer,">From ")) 
  1063. X          forwarded(buffer, from_whom); /* return address */
  1064. X        else if (first_word(buffer,"Subject:") ||
  1065. X             first_word(buffer,"Re:")) {
  1066. X          if (! subj++) {
  1067. X            remove_first_word(buffer);
  1068. X        strcpy(subject, buffer);
  1069. X          }
  1070. X        }
  1071. X        else if (first_word(buffer,"From:") ||
  1072. X            first_word(buffer, ">From:"))
  1073. X          parse_arpa_from(buffer, from_whom);
  1074. X        else if (buffer[0] == LINEFEED) {
  1075. X          if (verbose && count == 0)
  1076. X            printf("%s contains the following messages:\n\n",
  1077. X            user_mailbox?"Your mailbox" : "Folder");
  1078. X          in_header = 0;    /* in body of message! */
  1079. X          show_header(count+1, from_whom, subject);
  1080. X          from_whom[0] = 0;
  1081. X          subject[0] = 0;
  1082. X          count++;
  1083. X        }
  1084. X      }
  1085. X    }
  1086. X    return(count);
  1087. X}
  1088. X
  1089. Xint
  1090. Xreal_from(buffer, who)
  1091. Xchar *buffer, *who;
  1092. X{
  1093. X    /***** returns true iff 's' has the seven 'from' fields,
  1094. X           initializing the who to the sender *****/
  1095. X
  1096. X    char junk[SLEN];
  1097. X
  1098. X    junk[0] = '\0';
  1099. X    sscanf(buffer, "%*s %s %*s %*s %*s %*s %s",
  1100. X                who, junk);
  1101. X    return(junk[0] != '\0');
  1102. X}
  1103. X
  1104. Xforwarded(buffer, who)
  1105. Xchar *buffer, *who;
  1106. X{
  1107. X    /** change 'from' and date fields to reflect the ORIGINATOR of 
  1108. X        the message by iteratively parsing the >From fields... **/
  1109. X
  1110. X    char machine[SLEN], buff[SLEN], holding_from[SLEN];
  1111. X
  1112. X    machine[0] = '\0';
  1113. X    holding_from[0] = '\0';
  1114. X    sscanf(buffer, "%*s %s %*s %*s %*s %*s %*s %*s %*s %*s %s",
  1115. X                holding_from, machine);
  1116. X
  1117. X    if(machine[0] == '\0')    /* try for address with timezone in date */
  1118. X    sscanf(buffer, "%*s %s %*s %*s %*s %*s %*s %*s %*s %s",
  1119. X                holding_from, machine);
  1120. X
  1121. X    if (machine[0] == '\0') /* try for srm address */
  1122. X      sscanf(buffer, "%*s %s %*s %*s %*s %*s %*s %*s %s",
  1123. X                holding_from, machine);
  1124. X
  1125. X    if (machine[0] == '\0')
  1126. X      sprintf(buff, holding_from[0] ? holding_from : "anonymous");
  1127. X    else
  1128. X      sprintf(buff,"%s!%s", machine, holding_from);
  1129. X
  1130. X    strncpy(who, buff, SLEN);
  1131. X}
  1132. X
  1133. Xremove_first_word(string)
  1134. Xchar *string;
  1135. X{    /** removes first word of string, ie up to first non-white space
  1136. X        following a white space! **/
  1137. X
  1138. X    register int loc;
  1139. X
  1140. X    for (loc = 0; string[loc] != ' ' && string[loc] != '\0'; loc++) 
  1141. X        ;
  1142. X
  1143. X    while (string[loc] == ' ' || string[loc] == '\t')
  1144. X      loc++;
  1145. X    
  1146. X    move_left(string, loc);
  1147. X}
  1148. X
  1149. Xmove_left(string, chars)
  1150. Xchar string[];
  1151. Xint  chars;
  1152. X{
  1153. X    /** moves string chars characters to the left DESTRUCTIVELY **/
  1154. X
  1155. X    register int i;
  1156. X
  1157. X    chars--; /* index starting at zero! */
  1158. X
  1159. X    for (i=chars; string[i] != '\0' && string[i] != '\n'; i++)
  1160. X      string[i-chars] = string[i];
  1161. X
  1162. X    string[i-chars] = '\0';
  1163. X}
  1164. X
  1165. Xshow_header(count, from, subject)
  1166. Xint  count;
  1167. Xchar *from, *subject;
  1168. X{
  1169. X    /** output header in clean format, including abbreviation
  1170. X        of return address if more than one machine name is
  1171. X        contained within it! **/
  1172. X
  1173. X    char buffer[SLEN];
  1174. X    int  loc, i=0, exc=0;
  1175. X
  1176. X#ifndef INTERNET
  1177. X    char *p;
  1178. X    
  1179. X    if (chloc(from,'!') != -1 && chloc(from,'@') > 0) {
  1180. X      for (p=from;*p != '@'; p++) ;
  1181. X      *p = '\0';
  1182. X    }
  1183. X#endif
  1184. X
  1185. X    loc = strlen(from);
  1186. X
  1187. X    while (exc < 2 && loc > 0)
  1188. X      if (from[--loc] == '!')
  1189. X        exc++;
  1190. X
  1191. X    if (exc == 2) { /* lots of machine names!  Get last one */
  1192. X      loc++;
  1193. X      while (loc < strlen(from) && loc < SLEN)
  1194. X        buffer[i++] = from[loc++];
  1195. X      buffer[i] = '\0';
  1196. X      if (number)
  1197. X        printf("%3d: %-20s  %s\n", count, buffer, subject);
  1198. X      else
  1199. X        printf("%-20s  %s\n", buffer, subject);
  1200. X    }
  1201. X    else
  1202. X      if (number)
  1203. X        printf("%3d: %-20s  %s\n", count, from, subject);
  1204. X      else
  1205. X        printf("%-20s  %s\n", from, subject);
  1206. X}    
  1207. X
  1208. Xparse_arpa_from(buffer, newfrom)
  1209. Xchar *buffer, *newfrom;
  1210. X{
  1211. X    /** try to parse the 'From:' line given... It can be in one of
  1212. X        two formats:
  1213. X        From: Dave Taylor <hpcnou!dat>
  1214. X        or  From: hpcnou!dat (Dave Taylor)
  1215. X        Change 'newfrom' ONLY if sucessfully parsed this entry and
  1216. X        the resulting name is non-null! 
  1217. X    **/
  1218. X
  1219. X    char temp_buffer[SLEN], *temp;
  1220. X    register int i, j = 0, in_parens;
  1221. X
  1222. X    temp = (char *) temp_buffer;
  1223. X    temp[0] = '\0';
  1224. X
  1225. X    no_ret(buffer);        /* blow away '\n' char! */
  1226. X
  1227. X    if (lastch(buffer) == '>') {
  1228. X      for (i=strlen("From: "); buffer[i] != '\0' && buffer[i] != '<' &&
  1229. X           buffer[i] != '('; i++)
  1230. X        temp[j++] = buffer[i];
  1231. X      temp[j] = '\0';
  1232. X    }
  1233. X    else if (lastch(buffer) == ')') {
  1234. X      in_parens = 1;
  1235. X      for (i=strlen(buffer)-2; buffer[i] != '\0' && buffer[i] != '<'; i--) {
  1236. X        switch(buffer[i]) {
  1237. X        case ')':    in_parens++;
  1238. X            break;
  1239. X        case '(':    in_parens--;
  1240. X            break;
  1241. X        }
  1242. X        if(!in_parens) break;
  1243. X        temp[j++] = buffer[i];
  1244. X      }
  1245. X      temp[j] = '\0';
  1246. X      reverse(temp);
  1247. X    }
  1248. X
  1249. X/* this stuff copied from src/addr_util.c */
  1250. X#ifdef USE_EMBEDDED_ADDRESSES
  1251. X
  1252. X    /** if we have a null string at this point, we must just have a 
  1253. X        From: line that contains an address only.  At this point we
  1254. X        can have one of a few possibilities...
  1255. X
  1256. X        From: address
  1257. X        From: <address>
  1258. X        From: address ()
  1259. X    **/
  1260. X      
  1261. X    if (strlen(temp) == 0) {
  1262. X      if (lastch(buffer) != '>') {       
  1263. X        for (i=strlen("From:");buffer[i] != '\0' && buffer[i] != '('; i++)
  1264. X          temp[j++] = buffer[i];
  1265. X        temp[j] = '\0';
  1266. X      }
  1267. X      else {    /* get outta '<>' pair, please! */
  1268. X        for (i=strlen(buffer)-2;buffer[i] != '<' && buffer[i] != ':';i--)
  1269. X          temp[j++] = buffer[i];
  1270. X        temp[j] = '\0';
  1271. X        reverse(temp);
  1272. X      }
  1273. X    }
  1274. X#endif
  1275. X
  1276. X    if (strlen(temp) > 0) {        /* mess with buffer... */
  1277. X
  1278. X      /* remove leading spaces... */
  1279. X
  1280. X      while (whitespace(temp[0]))
  1281. X        temp = (char *) (temp + 1);        /* increment address! */
  1282. X
  1283. X      /* remove trailing spaces... */
  1284. X
  1285. X      i = strlen(temp) - 1;
  1286. X
  1287. X      while (whitespace(temp[i]))
  1288. X       temp[i--] = '\0';
  1289. X
  1290. X      /* remove surrounding paired quotation marks */
  1291. X      if((temp[i] == '"') & (*temp == '"')) {
  1292. X        temp[i] = '\0';
  1293. X        temp++;
  1294. X      }
  1295. X
  1296. X      /* if anything is left, let's change 'from' value! */
  1297. X
  1298. X      if (strlen(temp) > 0)
  1299. X        strcpy(newfrom, temp);
  1300. X    }
  1301. X}
  1302. X
  1303. Xreverse(string)
  1304. Xchar *string;
  1305. X{
  1306. X    /** reverse string... pretty trivial routine, actually! **/
  1307. X
  1308. X    char buffer[SLEN];
  1309. X    register int i, j = 0;
  1310. X
  1311. X    for (i = strlen(string)-1; i >= 0; i--)
  1312. X      buffer[j++] = string[i];
  1313. X
  1314. X    buffer[j] = '\0';
  1315. X
  1316. X    strcpy(string, buffer);
  1317. X}
  1318. SHAR_EOF
  1319. chmod 0444 utils/from.c || echo "restore of utils/from.c fails"
  1320. echo "x - extracting utils/listalias.c (Text)"
  1321. sed 's/^X//' << 'SHAR_EOF' > utils/listalias.c &&
  1322. X
  1323. Xstatic char rcsid[] = "@(#)$Id: listalias.c,v 2.3 89/03/25 21:47:50 syd Exp $";
  1324. X
  1325. X/*******************************************************************************
  1326. X *  The Elm Mail System  -  $Revision: 2.3 $   $State: Exp $
  1327. X *
  1328. X *             Copyright (c) 1986, 1987 Dave Taylor
  1329. X *             Copyright (c) 1988, 1989 USENET Community Trust
  1330. X *******************************************************************************
  1331. X * Bug reports, patches, comments, suggestions should be sent to:
  1332. X *
  1333. X *    Syd Weinstein, Elm Coordinator
  1334. X *    elm@dsinc.UUCP            dsinc!elm
  1335. X *
  1336. X *******************************************************************************
  1337. X * $Log:    listalias.c,v $
  1338. X * Revision 2.3  89/03/25  21:47:50  syd
  1339. X * Initial 2.2 Release checkin
  1340. X * 
  1341. X *
  1342. X ******************************************************************************/
  1343. X
  1344. X/** Program that lists all the available aliases.  This one uses the pipe 
  1345. X    command, feeding the stuff to egrep then sort, or just sort.
  1346. X
  1347. X**/
  1348. X
  1349. X#include <stdio.h>
  1350. X#include <fcntl.h>
  1351. X
  1352. X#include "defs.h"
  1353. X#include "sysdefs.h"
  1354. X
  1355. X#ifdef BSD
  1356. X  FILE *popen();
  1357. X#endif
  1358. X
  1359. Xchar *getenv();
  1360. X
  1361. Xmain(argc, argv)
  1362. Xint argc;
  1363. Xchar *argv[];
  1364. X{
  1365. X    FILE *datafile, *fd_pipe;
  1366. X    struct alias_rec hash_record;
  1367. X    int hashfile, count = 0;
  1368. X    char buffer[SLEN], fd_hash[SLEN], 
  1369. X         fd_data[SLEN], *home;
  1370. X
  1371. X    if (argc > 2) {
  1372. X      printf("Usage: listalias <optional-regular-expression>\n");
  1373. X      exit(1);
  1374. X    }
  1375. X
  1376. X    home = getenv("HOME");
  1377. X
  1378. X    sprintf(fd_hash, "%s/%s", home, ALIAS_HASH);
  1379. X    sprintf(fd_data, "%s/%s", home, ALIAS_DATA);
  1380. X
  1381. X    if (argc > 1)
  1382. X      sprintf(buffer, "egrep \"%s\" | sort", argv[1]);
  1383. X    else
  1384. X      sprintf(buffer, "sort");
  1385. X
  1386. X    if ((fd_pipe = popen(buffer, "w")) == NULL) {
  1387. X      if (argc > 1) 
  1388. X        printf("cannot open pipe to egrep program for expressions!\n");
  1389. X      fd_pipe = stdout;
  1390. X    }
  1391. X
  1392. X    do {
  1393. X
  1394. X      if ((hashfile = open(fd_hash, O_RDONLY)) > 0) {
  1395. X        if ((datafile = fopen(fd_data, "r")) == NULL) {
  1396. X          printf("Opened %s hash file, but couldn't open data file!\n",
  1397. X               count? "system" : "user");
  1398. X          goto next_file;
  1399. X        }
  1400. X    
  1401. X        /** Otherwise let us continue... **/
  1402. X
  1403. X        while (read(hashfile, &hash_record, sizeof (hash_record)) != 0) {
  1404. X          if (strlen(hash_record.name) > 0) {
  1405. X            fseek(datafile, hash_record.byte, 0L);
  1406. X            fgets(buffer, SLEN, datafile);
  1407. X            fprintf(fd_pipe, "%-15s  %s", hash_record.name, buffer);
  1408. X          }
  1409. X        }
  1410. X      }
  1411. X
  1412. Xnext_file: strcpy(fd_hash, system_hash_file);
  1413. X       strcpy(fd_data, system_data_file);
  1414. X
  1415. X    } while (++count < 2);
  1416. X
  1417. X    pclose(fd_pipe);
  1418. X
  1419. X    exit(0);
  1420. X}
  1421. SHAR_EOF
  1422. chmod 0444 utils/listalias.c || echo "restore of utils/listalias.c fails"
  1423. echo "x - extracting utils/mailrc.awk (Text)"
  1424. sed 's/^X//' << 'SHAR_EOF' > utils/mailrc.awk &&
  1425. X#
  1426. X# @(#)$Id: mailrc.awk,v 2.3 89/03/25 21:47:51 syd Exp $
  1427. X#    Copyright (c) 1986, 1987 Dave Taylor
  1428. X#    Copyright (c) 1988, 1989 USENET Community Trust
  1429. X# Bug reports, patches, comments, suggestions should be sent to:
  1430. X#
  1431. X#    Syd Weinstein, Elm Coordinator - elm@dsinc.UUCP
  1432. X#                     dsinc!elm
  1433. X#
  1434. X# $Log:    mailrc.awk,v $
  1435. X# Revision 2.3  89/03/25  21:47:51  syd
  1436. X# Initial 2.2 Release checkin
  1437. X# 
  1438. X#
  1439. X
  1440. X
  1441. XBEGIN { 
  1442. X    print "# MSG alias_text file, from a .mailrc file..." 
  1443. X    print ""
  1444. X      }
  1445. X
  1446. Xnext_line == 1 { 
  1447. X
  1448. X    next_line = 0;
  1449. X        group = ""
  1450. X    for (i = 1; i <= NF; i++) {
  1451. X      if (i == NF && $i == "\\") sep = ""
  1452. X      else                       sep = ", "
  1453. X    
  1454. X      if ($i == "\\") {
  1455. X        group = sprintf("%s,", group)
  1456. X        next_line = 1;
  1457. X      }
  1458. X      else if (length(group) > 0)
  1459. X        group = sprintf("%s%s%s", group, sep, $i);
  1460. X      else
  1461. X        group = $i;
  1462. X      }
  1463. X      print "\t" group
  1464. X
  1465. X    }
  1466. X
  1467. X$1 ~ /[Aa]lias|[Gg]roup/ { 
  1468. X
  1469. X    if ( NF == 3)
  1470. X      print $2 " : user alias : " $3;
  1471. X    else {
  1472. X      group = ""
  1473. X      for (i = 3; i <= NF; i++) {
  1474. X        if (i == NF && $i == "\\") sep = ""
  1475. X        else        sep = ", "
  1476. X    
  1477. X        if ($i == "\\") {
  1478. X           group = sprintf("%s,", group)
  1479. X           next_line = 1;
  1480. X        }
  1481. X        else if (length(group) > 0) 
  1482. X           group = sprintf("%s%s%s", group, sep, $i);
  1483. X        else
  1484. X           group = $i;
  1485. X        }
  1486. X        print $2 " : group alias : " group;
  1487. X      }
  1488. X     }
  1489. SHAR_EOF
  1490. chmod 0444 utils/mailrc.awk || echo "restore of utils/mailrc.awk fails"
  1491. echo "x - extracting utils/messages (Text)"
  1492. sed 's/^X//' << 'SHAR_EOF' > utils/messages &&
  1493. X: Use /bin/sh
  1494. X# messages: part of the Elm mail system
  1495. X# @(#)$Id: messages,v 2.1 89/03/03 17:46:59 syd Exp $
  1496. Xif [ "$2" != "" ]; then
  1497. X  echo Usage: messages \{folder-name\} 1>&2
  1498. X  exit 1
  1499. Xfi
  1500. Xif [ "$1" = "" ]; then
  1501. X  fname=$MAIL
  1502. X  optional="in your mailbox"
  1503. Xelse
  1504. X  fname=$1
  1505. X  optional="in folder $1"
  1506. Xfi
  1507. Xif [ -f "$fname" ]; then
  1508. X  mcount=`egrep -c "^From " $fname`
  1509. Xelse
  1510. X  exit 0
  1511. Xfi
  1512. Xif [ "$mcount" -eq 1 ]; then
  1513. X  echo There is $mcount message $optional.
  1514. Xelse
  1515. X  echo There are $mcount messages $optional.
  1516. Xfi
  1517. Xexit $mcount
  1518. SHAR_EOF
  1519. chmod 0444 utils/messages || echo "restore of utils/messages fails"
  1520. echo "x - extracting utils/newalias.c (Text)"
  1521. sed 's/^X//' << 'SHAR_EOF' > utils/newalias.c &&
  1522. X
  1523. Xstatic char rcsid[] = "@(#)$Id: newalias.c,v 2.7 89/03/25 21:47:53 syd Exp $";
  1524. X
  1525. X/*******************************************************************************
  1526. X *  The Elm Mail System  -  $Revision: 2.7 $   $State: Exp $
  1527. X *
  1528. X *             Copyright (c) 1986, 1987 Dave Taylor
  1529. X *             Copyright (c) 1988, 1989 USENET Community Trust
  1530. X *******************************************************************************
  1531. X * Bug reports, patches, comments, suggestions should be sent to:
  1532. X *
  1533. X *    Syd Weinstein, Elm Coordinator
  1534. X *    elm@dsinc.UUCP            dsinc!elm
  1535. X *
  1536. X *******************************************************************************
  1537. X * $Log:    newalias.c,v $
  1538. X * Revision 2.7  89/03/25  21:47:53  syd
  1539. X * Initial 2.2 Release checkin
  1540. X * 
  1541. X *
  1542. X ******************************************************************************/
  1543. X
  1544. X/** Install a new set of aliases for the 'Elm' mailer. 
  1545. X
  1546. X    If invoked with a specific filename, it assumes that
  1547. X  it is working with an individual users alias tables, and
  1548. X  generates the .alias.hash and .alias.data files in their
  1549. X  home directory.
  1550. X    If, however, it is invoked with no arguments, then
  1551. X  it assumes that the user is updating the system alias
  1552. X  file and uses the defaults for everything.
  1553. X
  1554. X  The format for the input file is;
  1555. X    alias1, alias2, ... = username = address
  1556. Xor  alias1, alias2, ... = groupname= member, member, member, ...
  1557. X                                     member, member, member, ...
  1558. X
  1559. X**/
  1560. X
  1561. X#include <stdio.h>
  1562. X#include "defs.h"
  1563. X#include "sysdefs.h"        /* ELM system definitions */
  1564. X
  1565. X#ifdef BSD
  1566. X#  include <sys/file.h>
  1567. X#else
  1568. X#  include <fcntl.h>
  1569. X#endif
  1570. X
  1571. Xstatic char ident[] = { WHAT_STRING };
  1572. X
  1573. X#define group(string)        (strpbrk(string,", ") != NULL)
  1574. X
  1575. Xstruct alias_rec
  1576. Xshash_table[MAX_SALIASES];    /* the actual hash table     */
  1577. X
  1578. Xstruct alias_rec
  1579. Xuhash_table[MAX_UALIASES];    /* the actual hash table     */
  1580. X
  1581. Xint  hash_table_loaded=0;    /* is system table actually loaded? */
  1582. X
  1583. Xint  buff_loaded;        /* for file input overlap... */
  1584. Xint  error= 0;            /* if errors, don't save!    */
  1585. Xint  is_system=0;        /* system file updating?     */
  1586. Xint  count=0;            /* how many aliases so far?  */
  1587. Xlong offset = 0L;        /* data file line offset!    */
  1588. Xchar home[SLEN];        /* the users home directory  */
  1589. X
  1590. Xmain(argc, argv)
  1591. Xint argc;
  1592. Xchar *argv[];
  1593. X{
  1594. X    FILE *in, *data;
  1595. X    char inputname[SLEN], hashname[SLEN], dataname[SLEN];
  1596. X    char buffer[LONG_STRING];
  1597. X    int  a, hash, count = 0, owner;
  1598. X
  1599. X    for (a = 1; a < argc; ++a) {
  1600. X      if (strcmp(argv[a], "-g") == 0)
  1601. X        is_system = 1;
  1602. X      else {
  1603. X        printf("Usage: %s [-g]\n", argv[0]);
  1604. X        exit(1);
  1605. X      }
  1606. X    }
  1607. X
  1608. X    if (is_system) {   /* update system aliases */
  1609. X      printf("Updating the system alias file...\n");
  1610. X
  1611. X      strcpy(inputname, system_text_file);
  1612. X      strcpy(hashname,  system_hash_file);
  1613. X      strcpy(dataname,  system_data_file);
  1614. X      init_table(shash_table, MAX_SALIASES);
  1615. X    }
  1616. X    else
  1617. X      printf("Updating your personal alias file...\n");
  1618. X    
  1619. X    if (! is_system) {
  1620. X      if (strcpy(home, getenv("HOME")) == NULL) {
  1621. X        printf("I'm confused - no HOME variable in environment!\n");
  1622. X        exit(1);
  1623. X      }
  1624. X
  1625. X      sprintf(inputname, "%s/%s", home, ALIAS_TEXT);
  1626. X      sprintf(hashname,  "%s/%s", home, ALIAS_HASH); 
  1627. X      sprintf(dataname,  "%s/%s", home, ALIAS_DATA); 
  1628. X
  1629. X      init_table(uhash_table, MAX_UALIASES); 
  1630. X
  1631. X      read_in_system(shash_table, sizeof shash_table);
  1632. X    }
  1633. X
  1634. X    if ((in = fopen(inputname,"r")) == NULL) {
  1635. X      /** let's see if they have the files in the old place... **/
  1636. X      sprintf(buffer, "%s/.alias_text", home);
  1637. X      if (access(buffer, ACCESS_EXISTS) != -1) {
  1638. X        update_alias_file_locations();
  1639. X        in = fopen(inputname, "r");
  1640. X      }
  1641. X      else {
  1642. X        printf("Couldn't open %s for input!\n", inputname);
  1643. X        exit(1);
  1644. X      }
  1645. X    }
  1646. X
  1647. X    if ((hash = open(hashname, O_WRONLY | O_CREAT, 0644)) == -1) {
  1648. X      printf("Couldn't open %s for output!\n", hashname);
  1649. X      exit(1);
  1650. X    }
  1651. X
  1652. X    if ((data = fopen(dataname,"w")) == NULL) {
  1653. X      printf("Couldn't open %s for output!\n", dataname);
  1654. X      exit(1);
  1655. X    }
  1656. X
  1657. X    buff_loaded = 0;     /* file buffer empty right now! */
  1658. X
  1659. X    while (get_alias(in, buffer) != -1) {
  1660. X      if (is_system)
  1661. X        put_alias(data, buffer, shash_table, MAX_SALIASES);    
  1662. X      else
  1663. X        put_alias(data, buffer, uhash_table, MAX_UALIASES);    
  1664. X      count++;
  1665. X    }
  1666. X
  1667. X    if (error) {
  1668. X      printf("\n** Not saving tables!  Please fix and re-run %s!\n",
  1669. X         argv[0]);
  1670. X      exit(1);
  1671. X    }
  1672. X    else {
  1673. X      if (is_system)
  1674. X        write(hash, shash_table, sizeof shash_table);
  1675. X      else
  1676. X        write(hash, uhash_table, sizeof uhash_table);
  1677. X
  1678. X      close(hash);
  1679. X      fclose(data);
  1680. X      close(in);
  1681. X    
  1682. X      printf("Processed %d aliases\n", count);
  1683. X      exit(0);
  1684. X    }
  1685. X}
  1686. X
  1687. Xint
  1688. Xget_alias(file, buffer)
  1689. XFILE *file;
  1690. Xchar *buffer;
  1691. X{
  1692. X    /* load buffer with the next complete alias from the file.
  1693. X       (this can include reading in multiple lines and appending
  1694. X       them all together!)  Returns EOF after last entry in file.
  1695. X    
  1696. X    Lines that start with '#' are assumed to be comments and are
  1697. X     ignored.  White space as the first field of a line is taken
  1698. X    to indicate that this line is a continuation of the previous. */
  1699. X
  1700. X    static char mybuffer[SLEN];
  1701. X    int    done = 0, first_read = 1;
  1702. X
  1703. X    /** get the first line of the entry... **/
  1704. X
  1705. X    buffer[0] = '\0';            /* zero out line */
  1706. X
  1707. X    do {
  1708. X      if (get_line(file, mybuffer, first_read) == -1) 
  1709. X        return(-1);
  1710. X      first_read = 0;
  1711. X      if (mybuffer[0] != '#')
  1712. X        strcpy(buffer, mybuffer);
  1713. X    } while (strlen(buffer) == 0);    
  1714. X
  1715. X    /** now read in the rest (if there is any!) **/
  1716. X
  1717. X    do {
  1718. X      if (get_line(file, mybuffer, first_read) == -1) {
  1719. X        buff_loaded = 0;    /* force a read next pass! */
  1720. X        return(0);    /* okay. let's just hand 'buffer' back! */
  1721. X      }
  1722. X      done = (! whitespace(mybuffer[0]));
  1723. X      if (! done)
  1724. X        strcat(buffer, mybuffer);
  1725. X      done = (done && mybuffer[0] != '#');
  1726. X    } while (! done);
  1727. X    
  1728. X    return(0);    /* no sweat! */
  1729. X}
  1730. X
  1731. Xput_alias(data, buffer, table, size)
  1732. XFILE *data;
  1733. Xchar *buffer;
  1734. Xstruct alias_rec table[];
  1735. Xint  size;
  1736. X{
  1737. X    /** break buffer down into three pieces: aliases, comment, and address.
  1738. X        Make the appropriate entries in the table (size) 
  1739. X    **/
  1740. X
  1741. X    char aliases[LONG_STRING], address[LONG_STRING];
  1742. X    char comment[LONG_STRING];
  1743. X    int  first, last, i = 0, j = 0;
  1744. X
  1745. X    remove_all(' ', TAB, buffer);
  1746. X
  1747. X    for (i=0; buffer[i] != '=' && i < LONG_STRING; i++)
  1748. X      aliases[i] = buffer[i];
  1749. X    aliases[i] = '\0';
  1750. X
  1751. X    for (i=strlen(buffer)-1; buffer[i] != '=' && i > 0; i--)
  1752. X      address[j++] = buffer[i];
  1753. X    address[j] = '\0';
  1754. X
  1755. X    comment[0] = '\0';    /* default to nothing at all... */
  1756. X
  1757. X    if ((first=strlen(aliases)+1) < (last=(strlen(buffer) - j))) {
  1758. X      extract_comment(comment, buffer, first, last); 
  1759. X    }
  1760. X
  1761. X    reverse(address);
  1762. X
  1763. X    add_to_table(data, aliases, comment, address, table, size);
  1764. X}
  1765. X
  1766. Xint
  1767. Xget_line(file, buffer, first_line)
  1768. XFILE *file;
  1769. Xchar *buffer;
  1770. Xint  first_line;
  1771. X{
  1772. X    /** read line from file.  If first_line and buff_loaded, 
  1773. X        then just return! **/
  1774. X
  1775. X    int stat;
  1776. X
  1777. X    if (first_line && buff_loaded) {
  1778. X      buff_loaded = 1;
  1779. X      return(0);
  1780. X    }
  1781. X
  1782. X    buff_loaded = 1;    /* we're going to get SOMETHING in the buffer */
  1783. X
  1784. X    stat = fgets(buffer, SLEN, file) == NULL ? -1 : 0;
  1785. X
  1786. X    if (stat != -1)
  1787. X      no_ret(buffer);
  1788. X
  1789. X    return(stat);
  1790. X}
  1791. X
  1792. Xreverse(string)
  1793. Xchar *string;
  1794. X{
  1795. X    /** reverse the order of the characters in string... 
  1796. X        uses a bubble-sort type of algorithm!                 **/
  1797. X    
  1798. X    register int f, l;
  1799. X    char     c;
  1800. X    
  1801. X    f = 0;
  1802. X    l = strlen(string) - 1;
  1803. X    
  1804. X    while (f < l) {
  1805. X      c = string[f];
  1806. X       string[f] = string[l];
  1807. X      string[l] = c;
  1808. X      f++;
  1809. X      l--;
  1810. X    }
  1811. X}
  1812. X
  1813. Xadd_to_table(data, aliases, comment, address, table, size)
  1814. XFILE *data;
  1815. Xchar *aliases, *comment, *address;
  1816. Xstruct alias_rec table[];
  1817. Xint  size;
  1818. X{
  1819. X    /** add address + comment to datafile, incrementing offset count 
  1820. X        (bytes), then for each alias in the aliases string, add to the
  1821. X        hash table, with the associated pointer value! **/
  1822. X
  1823. X    static char buf[SLEN], *word;
  1824. X    long additive = 1L;
  1825. X
  1826. X    word = buf;    /* use the allocated space! */
  1827. X
  1828. X    if (group(address)) {
  1829. X      check_group(address, aliases);
  1830. X      if (error) return;    /* don't do work if we aren't to save it! */
  1831. X      fprintf(data, "!%s\n", address);
  1832. X      additive = 2L;
  1833. X    }
  1834. X    else {
  1835. X      if (error) return;    /* don't do work if we aren't to save it! */
  1836. X      if (strlen(comment) > 0) {
  1837. X        fprintf(data, "%s (%s)\n", address, comment);
  1838. X        additive = (long) (strlen(comment) + 4);
  1839. X      }
  1840. X      else
  1841. X        fprintf(data, "%s\n", address, comment);
  1842. X    }
  1843. X
  1844. X    while ((word = (char *) strtok(aliases,", ")) != NULL) {
  1845. X      add_to_hash_table(word, offset, table, size);
  1846. X      aliases = NULL;    /* let's get ALL entries via 'strtok' */
  1847. X      count++;
  1848. X    }
  1849. X
  1850. X    if ( is_system ? count > MAX_SALIASES-35 : count > MAX_UALIASES-21) {
  1851. X      printf("** Too many aliases in file! **\n");
  1852. X      error++;
  1853. X    }
  1854. X
  1855. X    offset = (offset + (long) strlen(address) + additive);
  1856. X}    
  1857. X
  1858. Xremove_all(c1, c2, string)
  1859. Xchar c1, c2, *string;
  1860. X{
  1861. X    /* Remove all occurances of character 'c1' or 'c2' from the string.
  1862. X       Hacked (literally) to NOT remove ANY characters from within the
  1863. X       equals fields.  This will only be used if the line contains TWO
  1864. X       equalss (and comments with equalss in them are the kiss of death!)
  1865. X     */
  1866. X
  1867. X    char buffer[LONG_STRING];
  1868. X    register int i = 0, j = 0, first_equals = -1, last_equals = -1;
  1869. X    
  1870. X    for (i = 0; string[i] != '\0' && i < LONG_STRING; i++) {
  1871. X      if (string[i] != c1 && string[i] != c2)
  1872. X        buffer[j++] = string[i];
  1873. X
  1874. X      if (first_equals == -1 && string[i] == '=') {
  1875. X        first_equals = i;
  1876. X        for (last_equals=strlen(string);string[last_equals] != '='; 
  1877. X        last_equals--) ;
  1878. X      }
  1879. X      else if (i > first_equals && i < last_equals)
  1880. X       if (string[i] == c1 || string[i] == c2)
  1881. X         buffer[j++] = string[i];
  1882. X    }
  1883. X    
  1884. X    buffer[j] = '\0';
  1885. X    strcpy(string, buffer);
  1886. X}
  1887. X
  1888. Xadd_to_hash_table(word, offset, table, size)
  1889. Xchar *word;
  1890. Xlong  offset;
  1891. Xstruct alias_rec table[];
  1892. Xint   size;
  1893. X{
  1894. X    /** add word and offset to current hash table. **/
  1895. X    register int loc;
  1896. X    
  1897. X    if (strlen(word) > 20) {
  1898. X      printf("Bad alias name: %s.  Too long.\n", word);
  1899. SHAR_EOF
  1900. echo "End of part 23"
  1901. echo "File utils/newalias.c is continued in part 24"
  1902. echo "24" > s2_seq_.tmp
  1903. exit 0
  1904.  
  1905.